home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / vsoup11.zip / kill.cc < prev    next >
C/C++ Source or Header  |  1996-09-02  |  6KB  |  296 lines

  1. //  $Id: kill.cc 1.9 1996/09/02 13:22:34 hardy Exp $
  2. //
  3. //  This progam/module was written by Hardy Griech based on ideas and
  4. //  pieces of code from Chin Huang (cthuang@io.org).  Bug reports should
  5. //  be submitted to rgriech@ibm.net.
  6. //
  7. //  This file is part of soup++ for OS/2.  Soup++ including this file
  8. //  is freeware.  There is no warranty of any kind implied.  The terms
  9. //  of the GNU Gernal Public Licence are valid for this piece of software.
  10. //
  11. //  Kill file processing
  12. //
  13.  
  14.  
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <regexp.h>
  20.  
  21. #include "kill.hh"
  22. #include "mts.hh"
  23.  
  24.  
  25.  
  26. TKillFile::TKillFile( void )
  27. {
  28.     globalKill = groupKillList = cacheGroupKill = NULL;
  29.     cacheGroupName = xstrdup("");
  30. }   // TKillFile::TKillFile
  31.  
  32.  
  33.  
  34. void TKillFile::killGroup( Group *gp )
  35. {
  36.     Exp *ep1, *ep2;
  37.     
  38.     if (gp == NULL)
  39.     return;
  40.  
  41.     ep1 = gp->expList;
  42.     while (ep1 != NULL) {
  43.     if (ep1->re != NULL) {
  44. ////        delete ep1->re;
  45.     }
  46.     ep2 = ep1->next;
  47. ////    delete ep1;
  48.     ep1 = ep2;
  49.     }
  50. ////    delete gp->name;
  51. ////   delete gp;
  52. }   // TKillFile::killGroup
  53.  
  54.  
  55.  
  56. TKillFile::~TKillFile()
  57. {
  58.     Group *gp1, *gp2;
  59.  
  60. ////    delete cacheGroupName;
  61.  
  62.     killGroup( globalKill );
  63.     gp1 = groupKillList;
  64.     while (gp1 != NULL) {
  65.     gp2 = gp1->next;
  66.     killGroup( gp1 );
  67.     gp1 = gp2;
  68.     }
  69. }   // TKillFile::~TKillFile
  70.  
  71.  
  72.  
  73. TKillFile::Exp *TKillFile::readExp(const char *searchIn, const char *searchFor)
  74. {
  75.     char exp[BUFSIZ];
  76.     Exp *result;
  77.  
  78.     if (searchFor[0] == '\0')
  79.     return NULL;
  80.  
  81.     if (stricmp(searchIn, "header") == 0) {
  82.     strcpy(exp, searchFor);
  83.     } else {
  84.     strcpy( exp, "^" );
  85.     strcat( exp, searchIn );
  86.     strcat( exp, ":.*" );
  87.     strcat( exp, searchFor );
  88.     }
  89.  
  90.     result = new Exp;
  91.     result->next = NULL;
  92.     strlwr(exp);
  93.     result->re = regcompT(exp);
  94.     return result;
  95. }   // TKillFile::readExp
  96.  
  97.  
  98.  
  99. int TKillFile::readFile( const char *killFile, int maxLines )
  100. //
  101. //  Read kill file and compile regular expressions.
  102. //  Return:  -1 -> file not found, 0 -> syntax error, 1 -> ok
  103. //  Nicht so hanz das optimale:  besser wäre es eine Zustandsmaschine
  104. //  zusammenzubasteln...
  105. //
  106. {
  107.     char buf[BUFSIZ], name[FILENAME_MAX];
  108.     char searchIn[BUFSIZ], searchFor[BUFSIZ];
  109.     FILE *inf;
  110.     Group *pGroup, *pLastGroup;
  111.     Exp *pExp, *pLastExp;
  112.     char ok;
  113.  
  114.     globalKill = groupKillList = NULL;
  115.     TKillFile::maxLines = maxLines;
  116.  
  117.     if ((inf = fopenT(killFile, "r")) == NULL) {
  118.     return -1;
  119.     }
  120.  
  121.     sema.Request();
  122.  
  123.     pLastGroup = NULL;
  124.     ok = 1;
  125.  
  126.     //
  127.     //  read newsgroup name
  128.     //
  129.     while (ok  &&  fscanfT(inf, "%s%*[ \t\n]%[^\n]\n", name,buf) == 2) {
  130. #ifdef DEBUG_ALL
  131.     printfT( "name: '%s', '%s'\n",name,buf );
  132. #endif
  133.     if (name[0] == '#')        // comment
  134.         continue;
  135.  
  136.     if (buf[0] != '{' || buf[1] != '\0') {
  137.         ok = 0;
  138.         break;
  139.     }
  140.  
  141.     if (stricmp(name, "all") == 0) {
  142.         //
  143.         //  Allocate global kill entry.
  144.         //
  145.         if (globalKill == NULL) {
  146.         globalKill = new Group;
  147.         globalKill->name = NULL;
  148.         globalKill->expList = NULL;
  149.         }
  150.         pGroup = globalKill;
  151.     } else {
  152.         //
  153.         //  Allocate group kill entry.
  154.         //
  155.         pGroup = new Group;
  156.         pGroup->expList = NULL;
  157.         pGroup->name = xstrdup(name);
  158.         pGroup->next = NULL;
  159.  
  160.         if (pLastGroup == NULL)
  161.         groupKillList = pGroup;
  162.         else
  163.         pLastGroup->next = pGroup;
  164.         pLastGroup = pGroup;
  165.     }
  166.     pGroup->expList = NULL;
  167.  
  168.     //
  169.     //  Read kill expressions until closing brace.
  170.     //
  171.     pLastExp = NULL;
  172.     while (fscanfT(inf, "%s%*[ \t]%[^\n]\n", searchIn,searchFor) != -1) {
  173.         while (searchFor[0] != '\0'  &&  isspace(searchFor[strlen(searchFor)-1]))
  174.         searchFor[strlen(searchFor)-1] = '\0';
  175. #ifdef DEBUG_ALL
  176.         printfT( "search: '%s', '%s'\n",searchIn,searchFor );
  177. #endif
  178.         if (searchIn[0] == '#')      // comment
  179.         continue;
  180.         if (searchIn[0] == '}' && searchIn[1] == '\0')
  181.         break;
  182.         if ((pExp = readExp(searchIn,searchFor)) == NULL) {
  183.         ok = 0;
  184.         break;
  185.         }
  186.  
  187.         if (pLastExp == NULL)
  188.         pGroup->expList = pExp;
  189.         else
  190.         pLastExp->next = pExp;
  191.         pLastExp = pExp;
  192.     }
  193.     }
  194.     sema.Release();
  195.  
  196.     fcloseT(inf);
  197.  
  198.     if (!ok)
  199.     fprintfT(stderr, "error in kill file %s,\n\tsection %s\n", killFile,name);
  200.     return ok;
  201. }   // TKillFile::readFile
  202.  
  203.  
  204.  
  205. TKillFile::Group *TKillFile::getGroupP( const char *groupName )
  206. //
  207. //  return group kill for *groupName
  208. //
  209. {
  210.     Group *p;
  211.     Group *res;
  212.  
  213. #ifdef TRACE_ALL
  214. //    printfT( "TKillFile::getGroupP(%s)\n",groupName );
  215. #endif
  216.  
  217.     sema.Request();
  218.     if (stricmp(groupName,cacheGroupName) != 0) {
  219.     for (p = groupKillList; p != NULL; p = p->next) {
  220.         if (stricmp(p->name, groupName) == 0) {
  221.         xstrdup( &cacheGroupName, p->name );
  222.         cacheGroupKill = p;
  223.         break;
  224.         }
  225.     }
  226.     if (p == NULL) {
  227.         xstrdup( &cacheGroupName, "" );
  228.         cacheGroupKill = NULL;
  229.     }
  230.     }
  231.     res = cacheGroupKill;
  232.     sema.Release();
  233.     return res;
  234. }   // TKillFile::getGroupP
  235.  
  236.  
  237.  
  238. int TKillFile::matchExp(Group *pGroup, const char *buf)
  239. {
  240.     Exp *pExp;
  241.  
  242.     if (pGroup == NULL)
  243.     return 0;
  244.  
  245.     sema.Request();
  246.     for (pExp = pGroup->expList; pExp != NULL; pExp = pExp->next) {
  247.     if (regexecT(pExp->re, buf)) {
  248.         sema.Release();
  249.         return 1;
  250.     }
  251.     }
  252.     sema.Release();
  253.     return 0;
  254. }   // TKillFile::matchExp
  255.  
  256.  
  257.  
  258. int TKillFile::matchLine( const char *groupName, const char *line )
  259. //
  260. //  Check if line matches kill criteria.
  261. //  Return TRUE if article should be killed.
  262. //
  263. {
  264.     char *buf;
  265.     int match = 0;
  266.  
  267.     //
  268.     //  remove trailing '\n' and make lower cases
  269.     //
  270.     buf = (char *)xstrdup( line );
  271.     strlwr(buf);
  272.  
  273.     //
  274.     //  article too long ?
  275.     //
  276.     if (maxLines > 0 && strncmp(buf, "lines: ", 7) == 0) {
  277.     match = (atoi(buf+7) > maxLines);
  278.     }
  279.  
  280.     if ( !match) {
  281.     //
  282.     //  is there any match with the killFile ?
  283.     //
  284.     match = matchExp(globalKill, buf)  ||  matchExp(getGroupP(groupName), buf);
  285.     }
  286.     delete buf;
  287.     return match;
  288. }   // TKillFile::matchLine
  289.  
  290.  
  291.  
  292. int TKillFile::doKillQ( const char *groupName )
  293. {
  294.     return maxLines > 0  ||  globalKill != NULL  ||  getGroupP(groupName) != NULL;
  295. }   // doKillQ
  296.